﻿using System;

namespace Lambda3.VisualStudio.DataTools.Generators.Cpf
{
    public class Cpf
    {
        private readonly int _BaseValue;
        private readonly bool _IncludeGroupSeparator;
        private readonly bool _IncludeDigitSeparator;

        public Cpf(int baseValue, bool includeGroupSeparator = true, bool includeDigitSeparator = true)
        {
            if (baseValue <= 0)
            {
                throw new ArgumentOutOfRangeException("baseValue", "Base value must be a positive number");
            }

            if (baseValue > 999999999)
            {
                throw new ArgumentOutOfRangeException("baseValue", "Base value must be less than 999,999,999");
            }

            _BaseValue = baseValue;
            _IncludeGroupSeparator = includeGroupSeparator;
            _IncludeDigitSeparator = includeDigitSeparator;
        }

        public override string ToString()
        {
            return GetCpf();
        }

        private string GetCpf()
        {
            var baseFormat = _IncludeGroupSeparator ? "000'.'000'.'000" : "000000000";
            var digitsFormat = _IncludeDigitSeparator ? "'-'00" : "00";

            return _BaseValue.ToString(baseFormat) + Digits.ToString(digitsFormat);
        }

        public int Digits { 
            get 
            {
                return GetDigits();
            } 
        }

        private int GetDigits()
        {
            var digits = _BaseValue.ToString("000000000");

            var checkDigit1 = (
                ((((int)digits[0]) - 48) * 10) +
                ((((int)digits[1]) - 48) * 09) +
                ((((int)digits[2]) - 48) * 08) +
                ((((int)digits[3]) - 48) * 07) +
                ((((int)digits[4]) - 48) * 06) +
                ((((int)digits[5]) - 48) * 05) +
                ((((int)digits[6]) - 48) * 04) +
                ((((int)digits[7]) - 48) * 03) +
                ((((int)digits[8]) - 48) * 02)) % 11;
            
            checkDigit1 = checkDigit1 < 2 ? 0 : 11 - checkDigit1;

            var checkDigit2 = (
                ((((int)digits[0]) - 48) * 11) +
                ((((int)digits[1]) - 48) * 10) +
                ((((int)digits[2]) - 48) * 09) +
                ((((int)digits[3]) - 48) * 08) +
                ((((int)digits[4]) - 48) * 07) +
                ((((int)digits[5]) - 48) * 06) +
                ((((int)digits[6]) - 48) * 05) +
                ((((int)digits[7]) - 48) * 04) +
                ((((int)digits[8]) - 48) * 03) +
                checkDigit1 * 2) % 11;

            checkDigit2 = checkDigit2 < 2 ? 0 : 11 - checkDigit2;


            return (checkDigit1 * 10) + checkDigit2;
        }
    }
}
